/**
 * Copyright (c) 2022 Presto Labs Pte. Ltd.
 * Author: Ju
 */

#pragma once

#include <boost/asio/io_service.hpp>
#include <cstdint>
#include <iostream>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>

#include "coin2/exchange/base/order/control/network/tcp_connection.h"
#include "coin2/exchange/base/order/control/network/tcp_server.h"
namespace coin2::exchange::base::order {

enum ControlType : uint8_t {
  EnableRawLog = 1,
  DisableRawLog = 2,
};

using Task = std::function<void()>;
class ControlHandler : public TcpServer::Callback,
                       public TcpConnection::Callback {
 public:
  class Callback {
   public:
    virtual ~Callback() = default;
    // TODO(Ju) support for more control types
    virtual void OnEvent(ControlType uri) = 0;
  };

  struct Menu {
    void AddOpt(std::pair<std::string, std::string> opt, Task task);
    bool Process(std::string key);
    std::string HelpDoc();
    std::unordered_map<std::string, std::string> opts_;
    std::unordered_map<std::string, Task> func_;
  };

  ControlHandler(boost::asio::io_context *ioc, Callback *callback);
  ~ControlHandler();

  void RegisterCallback(Callback *callback);

 private:
  // inherit from TcpServer::Callback
  void OnConnect(std::weak_ptr<TcpConnection> conn) override;

  // inherit from TcpConnection::Callback
  void OnRawDataReceived(std::weak_ptr<TcpConnection> conn, char *buff,
                         uint32_t len) override;

  void Init();
  void ProcessLine(char *buff, uint32_t len);
  void Parse();

 private:
  boost::asio::io_context *ioc_;
  Callback *callback_;
  std::unique_ptr<TcpServer> tcp_server_;
  std::weak_ptr<TcpConnection> tcp_conn_;
  std::string line_;
  Menu menu_;
};

inline void ControlHandler::RegisterCallback(Callback *callback) {
  callback_ = callback;
}

}  // namespace coin2::exchange::base::order
